<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>多数字段 | Elasticsearch: 权威指南 | Elastic</title>
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
</head>
<body>
<div class="main-container">
    <section id="content">
        
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原文地址: <a href="https://www.elastic.co/guide/cn/elasticsearch/guide/current/most-fields.html" rel="nofollow">https://www.elastic.co/guide/cn/elasticsearch/guide/current/most-fields.html</a>, 版权归 www.elastic.co 所有<br/>
                            英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/guide/current/most-fields.html" rel="nofollow">https://www.elastic.co/guide/en/elasticsearch/guide/current/most-fields.html</a>
                            </div>
                        <!-- start body -->
                  <div class="page_header">
<b>请注意:</b><br>本书基于 Elasticsearch 2.x 版本，有些内容可能已经过时。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: 权威指南</a></span>
»
<span class="breadcrumb-link"><a href="search-in-depth.html">深入搜索</a></span>
»
<span class="breadcrumb-link"><a href="multi-field-search.html">多字段搜索</a></span>
»
<span class="breadcrumb-node">多数字段</span>
</div>
<div class="navheader">
<span class="prev">
<a href="multi-match-query.html">« multi_match 查询</a>
</span>
<span class="next">
<a href="_cross_fields_entity_search.html">跨字段实体搜索 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="most-fields"></a>多数字段<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/110_Multi_Field_Search/30_Most_fields.asciidoc">edit</a>
</h2>
</div></div></div>
<p>全文搜索被称作是 <em>召回率（Recall）</em> 与 <em>精确率（Precision）</em> 的战场： <em>召回率</em> ——返回所有的相关文档； <em>精确率</em> ——不返回无关文档。目的是在结果的第一页中为用户呈现最为相关的文档。</p>
<p>为了提高召回率的效果，我们扩大搜索范围——不仅返回与用户搜索词精确匹配的文档，还会返回我们认为与查询相关的所有文档。如果一个用户搜索 “quick brown box” ，一个包含词语 <code class="literal">fast foxes</code> 的文档被认为是非常合理的返回结果。</p>
<p>如果包含词语 <code class="literal">fast foxes</code> 的文档是能找到的唯一相关文档，那么它会出现在结果列表的最上面，但是，如果有 100 个文档都出现了词语 <code class="literal">quick brown fox</code> ，那么这个包含词语 <code class="literal">fast foxes</code> 的文档当然会被认为是次相关的，它可能处于返回结果列表更下面的某个地方。当包含了很多潜在匹配之后，我们需要将最匹配的几个置于结果列表的顶部。</p>
<p>提高全文相关性精度的常用方式是为同一文本建立多种方式的索引，每种方式都提供了一个不同的相关度信号 <em>signal</em> 。主字段会以尽可能多的形式的去匹配尽可能多的文档。举个例子，我们可以进行以下操作：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
使用词干提取来索引 <code class="literal">jumps</code> 、 <code class="literal">jumping</code> 和 <code class="literal">jumped</code> 样的词，将 <code class="literal">jump</code> 作为它们的词根形式。这样即使用户搜索 <code class="literal">jumped</code> ，也还是能找到包含 <code class="literal">jumping</code> 的匹配的文档。
</li>
<li class="listitem">
将同义词包括其中，如 <code class="literal">jump</code> 、 <code class="literal">leap</code> 和 <code class="literal">hop</code> 。
</li>
<li class="listitem">
移除变音或口音词：如 <code class="literal">ésta</code> 、 <code class="literal">está</code> 和 <code class="literal">esta</code> 都会以无变音形式 <code class="literal">esta</code> 来索引。
</li>
</ul>
</div>
<p>尽管如此，如果我们有两个文档，其中一个包含词 <code class="literal">jumped</code> ，另一个包含词 <code class="literal">jumping</code> ，用户很可能期望前者能排的更高，因为它正好与输入的搜索条件一致。</p>
<p>为了达到目的，我们可以将相同的文本索引到其他字段从而提供更为精确的匹配。一个字段可能是为词干未提取过的版本，另一个字段可能是变音过的原始词，第三个可能使用 <em>shingles</em> 提供 <a class="xref" href="proximity-matching.html" title="近似匹配">词语相似性</a> 信息。这些附加的字段可以看成提高每个文档的相关度评分的信号 <em>signals</em> ，能匹配字段的越多越好。</p>
<p>一个文档如果与广度匹配的主字段相匹配，那么它会出现在结果列表中。如果文档同时又与 <em>signal</em> 信号字段匹配，那么它会获得额外加分，系统会提升它在结果列表中的位置。</p>
<p>我们会在本书稍后对同义词、词相似性、部分匹配以及其他潜在的信号进行讨论，但这里只使用词干已提取（stemmed）和未提取（unstemmed）的字段作为简单例子来说明这种技术。</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_多字段映射"></a>多字段映射<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/110_Multi_Field_Search/30_Most_fields.asciidoc">edit</a>
</h3>
</div></div></div>
<p>首先要做的事情就是对我们的字段索引两次：一次使用词干模式以及一次非词干模式。为了做到这点，采用 <em>multifields</em> 来实现，已经在 <a class="xref" href="multi-fields.html" title="字符串排序与多字段">multifields</a> 有所介绍：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">DELETE /my_index

PUT /my_index
{
    "settings": { "number_of_shards": 1 }, <a id="CO71-1"></a><i class="conum" data-value="1"></i>
    "mappings": {
        "my_type": {
            "properties": {
                "title": { <a id="CO71-2"></a><i class="conum" data-value="2"></i>
                    "type":     "string",
                    "analyzer": "english",
                    "fields": {
                        "std":   { <a id="CO71-3"></a><i class="conum" data-value="3"></i>
                            "type":     "string",
                            "analyzer": "standard"
                        }
                    }
                }
            }
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/110_Multi_Field_Search/30_Most_fields.json"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO71-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>参考 <a class="xref" href="relevance-is-broken.html" title="被破坏的相关度！">被破坏的相关度</a>.</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO71-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">title</code> 字段使用 <code class="literal">english</code> 英语分析器来提取词干。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO71-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">title.std</code> 字段使用 <code class="literal">standard</code> 标准分析器，所以没有词干提取。</p>
</td>
</tr>
</table>
</div>
<p>接着索引一些文档：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">PUT /my_index/my_type/1
{ "title": "My rabbit jumps" }

PUT /my_index/my_type/2
{ "title": "Jumping jack rabbits" }</pre>
</div>
<div class="sense_widget" data-snippet="snippets/110_Multi_Field_Search/30_Most_fields.json"></div>
<p>这里用一个简单 <code class="literal">match</code> 查询 <code class="literal">title</code> 标题字段是否包含 <code class="literal">jumping rabbits</code> （跳跃的兔子）：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /my_index/_search
{
   "query": {
        "match": {
            "title": "jumping rabbits"
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/110_Multi_Field_Search/30_Most_fields.json"></div>
<p>因为有了 <code class="literal">english</code> 分析器，这个查询是在查找以 <code class="literal">jump</code> 和 <code class="literal">rabbit</code> 这两个被提取词的文档。两个文档的 <code class="literal">title</code> 字段都同时包括这两个词，所以两个文档得到的评分也相同：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "hits": [
     {
        "_id": "1",
        "_score": 0.42039964,
        "_source": {
           "title": "My rabbit jumps"
        }
     },
     {
        "_id": "2",
        "_score": 0.42039964,
        "_source": {
           "title": "Jumping jack rabbits"
        }
     }
  ]
}</pre>
</div>
<p>如果只是查询 <code class="literal">title.std</code> 字段，那么只有文档 2 是匹配的。尽管如此，如果同时查询两个字段，然后使用 <code class="literal">bool</code> 查询将评分结果 <em>合并</em> ，那么两个文档都是匹配的（ <code class="literal">title</code> 字段的作用），而且文档 2 的相关度评分更高（ <code class="literal">title.std</code> 字段的作用）：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":  "jumping rabbits",
            "type":   "most_fields", <a id="CO72-1"></a><i class="conum" data-value="1"></i>
            "fields": [ "title", "title.std" ]
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/110_Multi_Field_Search/30_Most_fields.json"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO72-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>我们希望将所有匹配字段的评分合并起来，所以使用 <code class="literal">most_fields</code> 类型。这让 <code class="literal">multi_match</code> 查询用 <code class="literal">bool</code> 查询将两个字段语句包在里面，而不是使用 <code class="literal">dis_max</code> 查询。</p>
</td>
</tr>
</table>
</div>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "hits": [
     {
        "_id": "2",
        "_score": 0.8226396, <a id="CO73-1"></a><i class="conum" data-value="1"></i>
        "_source": {
           "title": "Jumping jack rabbits"
        }
     },
     {
        "_id": "1",
        "_score": 0.10741998, <a id="CO73-2"></a><i class="conum" data-value="1"></i>
        "_source": {
           "title": "My rabbit jumps"
        }
     }
  ]
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO73-1"><i class="conum" data-value="1"></i></a><a href="#CO73-2"></a></p>
</td>
<td align="left" valign="top">
<p>文档 2 现在的评分要比文档 1 高。</p>
</td>
</tr>
</table>
</div>
<p>用广度匹配字段 <code class="literal">title</code> 包括尽可能多的文档——以提升召回率——同时又使用字段 <code class="literal">title.std</code> 作为 <em>信号</em> 将相关度更高的文档置于结果顶部。</p>
<p>每个字段对于最终评分的贡献可以通过自定义值 <code class="literal">boost</code> 来控制。比如，使 <code class="literal">title</code> 字段更为重要，这样同时也降低了其他信号字段的作用：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":       "jumping rabbits",
            "type":        "most_fields",
            "fields":      [ "title^10", "title.std" ] <a id="CO74-1"></a><i class="conum" data-value="1"></i>
        }
    }
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/110_Multi_Field_Search/30_Most_fields.json"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO74-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">title</code> 字段的 <code class="literal">boost</code> 的值为 <code class="literal">10</code> 使它比 <code class="literal">title.std</code> 更重要。</p>
</td>
</tr>
</table>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="multi-match-query.html">« multi_match 查询</a>
</span>
<span class="next">
<a href="_cross_fields_entity_search.html">跨字段实体搜索 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>